class Entrust {
  #id;
  #type; // 委托类型
  #lever; // 杠杆倍数
  #indexPrice; // 价格
  #btcCount; // 委托总量
  #exInfo; // 附加数据
  #timestamp = Date.now();
  #isShort; // 是否做空
  #isOpen; // 是否开仓
  #usdBond;
  #isCompleted;
  #completedTimestamp;
  #finalPrice;
  #isCancelled;
  #cancelledTimestamp;

  constructor({
    id,
    type,
    lever,
    indexPrice,
    btcCount,
    isOpen = true,
    isShort,
    usdBond,
    exInfo = {},
    isCompleted = false,
    completedTimestamp = 0,
    isCancelled = false,
    cancelledTimestamp = 0,
    finalprice = null,
  }) {
    this.#id = id;
    this.#type = type;
    this.#lever = lever;
    this.#exInfo = exInfo;
    this.#indexPrice = indexPrice;
    this.#isShort = isShort;
    this.#btcCount = btcCount;
    this.#isOpen = isOpen;
    this.#usdBond = usdBond;
    this.#isCompleted = isCompleted;
    this.#completedTimestamp = completedTimestamp;
    this.#isCancelled = isCancelled;
    this.#cancelledTimestamp = cancelledTimestamp;
    this.#finalPrice = finalprice;
  }

  get isCancelled() {
    return this.#isCancelled;
  }

  get cancelledTimestamp() {
    return this.#cancelledTimestamp;
  }

  get isCompleted() {
    return this.#isCompleted;
  }

  get completedTimestamp() {
    return this.#completedTimestamp;
  }

  get usdBond() {
    return this.#usdBond;
  }

  get id() {
    return this.#id;
  }

  get isOpen() {
    return this.#isOpen;
  }

  get btcCount() {
    return this.#btcCount;
  }

  get isShort() {
    return this.#isShort;
  }

  get exInfo() {
    return JSON.parse(JSON.stringify(this.#exInfo));
  }

  get lever() {
    return this.#lever;
  }

  get indexPrice() {
    return this.#indexPrice;
  }

  get type() {
    return this.#type;
  }

  get timestamp() {
    return this.#timestamp;
  }

  get finalPrice() {
    return this.#finalPrice;
  }

  complete(finalPrice) {
    if (this.#isCompleted) {
      throw new Error(
        "Could not complete a entrust witch is already completed"
      );
    }
    this.#isCompleted = true;
    this.#completedTimestamp = Date.now();
    this.#finalPrice = finalPrice;
  }

  cancel() {
    if (this.#isCancelled) {
      throw new Error("Could not cancel a entrust witch is already cancelled");
    }
    this.#isCancelled = true;
    this.#cancelledTimestamp = Date.now();
  }
}

class Position {
  #avgFinalPrice; // 成交价
  #btcCount; // 数量
  #timestamp = Date.now();
  #usdBond;
  #isShort;
  #id;

  constructor({ id, avgFinalPrice, btcCount, usdBond, isShort }) {
    this.#id = id;
    this.#avgFinalPrice = avgFinalPrice;
    this.#btcCount = btcCount;
    this.#isShort = isShort;
    this.#usdBond = usdBond;
  }

  get isShort() {
    return this.#isShort;
  }

  get avgFinalPrice() {
    return this.#avgFinalPrice;
  }

  get id() {
    return this.#id;
  }

  get usdBond() {
    return this.#usdBond;
  }

  get timestamp() {
    return this.#timestamp;
  }

  get assert() {
    return this.#avgFinalPrice * this.#btcCount;
  }

  get btcCount() {
    return this.#btcCount;
  }

  calcExpectUnwindPrice(btcBond) {
    if (this.#isShort) {
      return this.#avgFinalPrice + btcBond / this.#btcCount;
    }
    return this.#avgFinalPrice - btcBond / this.#btcCount;
  }

  calcProfit(indexPrice) {
    let newAssert = indexPrice * this.#btcCount;
    if (this.#isShort) {
      return this.assert - newAssert;
    }
    return newAssert - this.assert;
  }

  calcLever() {
    return Math.floor((this.#btcCount * this.#avgFinalPrice) / this.#usdBond);
  }

  calcProfitRate(indexPrice) {
    let profit = this.calcProfit(indexPrice);
    if (profit < 0) {
      return -(Math.abs(profit) / this.#usdBond);
    }
    return profit / this.#usdBond;
  }
}

export { Entrust, Position };
